home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / math / alged34.zip / ALGEDSRC.ZIP / ALGSHOW.C < prev    next >
C/C++ Source or Header  |  1996-06-06  |  15KB  |  583 lines

  1. /*--------------------------------------------------------------------
  2.    Alged:  Algebra Editor    henckel@vnet.ibm.com
  3.  
  4.    Copyright (c) 1994 John Henckel
  5.    Permission to use, copy, modify, distribute and sell this software
  6.    and its documentation for any purpose is hereby granted without fee,
  7.    provided that the above copyright notice appear in all copies.
  8. */
  9. #include "alged.h"
  10. #include <alloc.h>
  11. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  12.  
  13.     The following functions relate to displaying expressions on the
  14.     screen.
  15. */
  16.  
  17. /*-----------------------------------------------------------------
  18.    twirl - this spins a little status indicator on the bottom
  19.    of the display to reassure the user in long calculations.
  20. */
  21. void twirl(void) {
  22.   static char c[] = "/-\\|";
  23.   static int i=0;
  24.   gotoxy(5,ti.screenheight);
  25.   putch(c[i]);
  26.   if (++i > 3) i=0;
  27. }
  28. /*--------------------------------------------------------------------
  29.    debug dump
  30. */
  31. void dumpnode(node *p,int tab) {
  32.   int i;
  33.   for (i=0; i<tab; ++i) putch(' ');
  34.   cprintf("%p %d %d (%d %d) %d '%s'\r\n",p,p->kind,p->nump,
  35.          p->px,p->py,p->sy,p->name);
  36.   for (i=0; i<p->nump; ++i)
  37.     dumpnode(p->parm[i],tab+2);
  38. }
  39.  
  40. /*--------------------------------------------------------------------
  41.    re compute size of each node
  42. */
  43. void resize(node *p,int ppr) {
  44.   double x;
  45.   int mpr,i;
  46.   mpr = pr[p->kind];
  47.   p->ay = 0;
  48.   switch (p->kind) {
  49.   case NUM:
  50.     x = fabs(p->value);
  51.     p->name[0] = 0;
  52.     if (p->value<0) strcat(p->name,"-");
  53.     if (x==M_PI)       strcat(p->name,piname);
  54.     else if (x==M_E)   strcat(p->name,ename);
  55.     else if (x==HUGE_VAL) strcat(p->name,infname);
  56.     else if (ch8 && x==0.5) strcat(p->name,halfname);
  57.     else if (ch8 && x==0.25) strcat(p->name,qtrname);
  58.     else         sprintf(p->name,"%1.15G",p->value);
  59.     p->sy=1;
  60.     p->sx=strlen(p->name);
  61.     if (!point && strchr(p->name,'.')) *strchr(p->name,'.') = ',';
  62.     break;
  63.   case BAD:
  64.     strcpy(p->name,errname);    /* fall thru */
  65.   case VAR:
  66.     p->sy=1;
  67.     p->sx=strlen(p->name);
  68.     break;
  69.   case EQU:
  70.   case ADD:
  71.   case SUB:
  72.     p->sx = 3;
  73.     if (mpr<ppr) p->sx += 2;         /* parens */
  74.     resize(p->lf,mpr);
  75.     resize(p->rt,mpr+1);         /* +1 = a hack */
  76.     p->sy = max(p->lf->sy,p->rt->sy);
  77.     p->sx += p->lf->sx + p->rt->sx;
  78.     strcpy(p->name,kname[p->kind]);
  79.     break;
  80.   case MUL:
  81.     p->sx = 1;
  82.     if (mpr<ppr) p->sx += 2;         /* parens */
  83.     resize(p->lf,mpr);
  84.     resize(p->rt,mpr+1);         /* +1 = a hack */
  85.     p->sy = max(p->lf->sy,p->rt->sy);
  86.     p->sx += p->lf->sx + p->rt->sx;
  87.     strcpy(p->name,kname[p->kind]);
  88.     break;
  89.   case DIV:
  90.     resize(p->lf,1);       /* 1 = div suppresses parens */
  91.     resize(p->rt,1);
  92.     p->sx = max(p->lf->sx,p->rt->sx) + 2;
  93.     p->sy = p->lf->sy + p->rt->sy + 1;
  94.     p->ay = p->lf->sy - p->rt->sy;
  95.     if (p->ay <0) p->ay--;
  96.     p->ay /= 2;
  97.     if (mpr<ppr) p->sx += 2;         /* parens */
  98.     strcpy(p->name,kname[p->kind]);
  99.     break;
  100.   case EXP:
  101.     resize(p->lf,mpr+1);
  102.     resize(p->rt,mpr);
  103.     p->sx = p->lf->sx + p->rt->sx;
  104.     p->sy = p->lf->sy + p->rt->sy;
  105.     p->ay = p->rt->sy - p->lf->sy;
  106.     if (p->ay >0) p->ay++;
  107.     p->ay /= 2;
  108.     if (mpr<ppr) p->sx += 2;         /* parens */
  109.     strcpy(p->name,kname[p->kind]);
  110.     break;
  111.   case FUN:
  112.     p->sx = strlen(p->name) + 1;     /* 2 parens JDH check this! */
  113.     p->sy = 0;
  114.     for (i=0; i<p->nump; ++i) {
  115.       resize(p->parm[i],mpr);
  116.       setmax(p->sy,p->parm[i]->sy);
  117.       p->sx += 1 + p->parm[i]->sx;     /* 1 comma */
  118.     }
  119.     break;
  120.   default:
  121.     printf(msg[14]);
  122.     pause;
  123.   }
  124. }
  125. /*--------------------------------------------------------------------
  126.    leftpar - print a left parenthesis
  127. */
  128. void leftpar(int h) {
  129.   int i;
  130.   if (h<2) {
  131.     putch('('); return; }
  132.   relxy(0,-h/2);
  133.   putch(ulc);
  134.   for (i=0; i<h-2; ++i) {
  135.     relxy(-1,1);
  136.     putch(vline);
  137.   }
  138.   relxy(-1,1);
  139.   putch(llc);
  140. }
  141. /*--------------------------------------------------------------------
  142.    rightpar - print a right parenthesis
  143. */
  144. void rightpar(int h) {
  145.   int i;
  146.   if (h<2) {
  147.     putch(')'); return; }
  148.   relxy(0,-h/2);
  149.   putch(urc);
  150.   for (i=0; i<h-2; ++i) {
  151.     relxy(-1,1);
  152.     putch(vline);
  153.   }
  154.   relxy(-1,1);
  155.   putch(lrc);
  156. }
  157. /*-----------------------------------------------------------------
  158.    fix attributes
  159. */
  160. int fixattr(node *p) {
  161.   gettextinfo(&ti);
  162.   if (p==src) textattr(bold1);
  163.   return ti.attribute;
  164. }
  165.  
  166. #define seen (x > 0 && x < ti.screenwidth)
  167.  
  168. /*--------------------------------------------------------------------
  169.    print expression
  170. */
  171. void show(node *p,int ppr,int x,int y) {
  172.   int mpr,i,z,s0,s1,attr;
  173.   mpr = pr[p->kind];
  174.  
  175.   if (yadj) y = y + p->ay;           /* adjust y */
  176.   gotoxy(x,y);
  177.   attr=fixattr(p);         /* save old attribute */
  178.  
  179.   switch (p->kind) {
  180.   case NUM:
  181.   case BAD:
  182.   case VAR:
  183.     p->px = x; p->py = y;
  184.     i = strlen(p->name); z = 0;
  185.     if (x > ti.screenwidth) break;
  186.     if (i+x > ti.screenwidth) i = ti.screenwidth - x;
  187.     if (x < 1) { gotoxy(1,y); z = -x; }
  188.     if (z < i) cprintf("%.*s",i-z,p->name+z);
  189.     break;
  190.   case EQU:
  191.   case ADD:
  192.   case SUB:
  193.     if (mpr<ppr) { if (seen) leftpar(p->sy); ++x; }     /* parens */
  194.     show(p->lf,mpr,x,y);
  195.     x += p->lf->sx + 1;
  196.     gotoxy(x-1,y);
  197.     fixattr(p);
  198.     if (seen) cprintf(" %s ",kname[p->kind]);
  199.     show(p->rt,mpr+1,x+2,y);
  200.     p->px = x; p->py = y;
  201.     if (mpr<ppr) {
  202.       x += 2+p->rt->sx;
  203.       gotoxy(x,y);
  204.       fixattr(p);
  205.       if (seen) rightpar(p->sy);                 /* parens */
  206.     }
  207.     break;
  208.   case MUL:
  209.     if (mpr<ppr) { if (seen) leftpar(p->sy); ++x; }     /* parens */
  210.     show(p->lf,mpr,x,y);
  211.     x += p->lf->sx;
  212.     gotoxy(x,y);
  213.     fixattr(p);
  214.     if (seen) cputs(ch8 ? kname[p->kind] : "*");
  215.     show(p->rt,mpr+1,x+1,y);
  216.     p->px = x; p->py = y;
  217.     if (mpr<ppr) {
  218.       x += 1+p->rt->sx;
  219.       gotoxy(x,y);
  220.       fixattr(p);
  221.       if (seen) rightpar(p->sy);                 /* parens */
  222.     }
  223.     break;
  224.   case DIV:
  225.     if (seen) for (i=0; i<p->sx; ++i) {
  226.       if (x+i < ti.screenwidth) putch(hline);
  227.     }
  228.     else if (x<1 && 0<(i=x+p->sx)) {
  229.       gotoxy(1,y); while (--i) putch(hline);
  230.     }
  231.     p->px = x; p->py = y;
  232.     if (mpr<ppr) {
  233.       gotoxy(x,y);
  234.       if (seen) leftpar(p->sy);       /* parens */
  235.     }
  236.     show(p->lf,1,x + (p->sx - p->lf->sx)/2,
  237.                       y - (p->lf->sy + 1)/2);
  238.     fixattr(p);
  239.     show(p->rt,1,x + (p->sx - p->rt->sx)/2,
  240.                       y + (p->rt->sy + 2)/2);
  241.     if (mpr<ppr) {
  242.       x+=p->sx-1;
  243.       gotoxy(x,y);
  244.       fixattr(p);
  245.       if (seen) rightpar(p->sy);         /* parens */
  246.     }
  247.     break;
  248.   case EXP:
  249.     if (mpr<ppr) { if (seen) leftpar(p->sy); ++x; }     /* parens */
  250.     show(p->rt,mpr  ,x + p->lf->sx,y - (p->rt->sy + 1)/2);
  251.     fixattr(p);
  252.     show(p->lf,mpr+1,x,            y + (p->lf->sy + 0)/2);
  253.     p->px = x + p->lf->sx - 1;
  254.     p->py = y - 1;
  255.     if (mpr<ppr) {
  256.       x += p->sx-2;
  257.       gotoxy(x,y);
  258.       fixattr(p);
  259.       if (seen) rightpar(p->sy);         /* parens */
  260.     }
  261.     break;
  262.   case FUN:
  263.     p->px = x; p->py = y;
  264.     if (seen) {
  265.       cputs(p->name);
  266.       leftpar(p->sy);
  267.     }
  268.     x += strlen(p->name) + 1;
  269.     for (i=0; ; ) {
  270.       show(p->parm[i],mpr,x,y);
  271.       x += p->parm[i]->sx;
  272.       gotoxy(x,y);
  273.       fixattr(p);
  274.       if (++i >= p->nump) break;
  275.       if (seen) putch(comma);
  276.       ++x;
  277.     }
  278.     if (seen) rightpar(p->sy);         /* parens */
  279.     break;
  280.   default:
  281.     printf(msg[15]);
  282.     pause;
  283.   }
  284.   textattr(attr);
  285. }
  286. /*-----------------------------------------------------------------
  287.    This test the integrity of the heap and returns the amount of
  288.    space USED.
  289. */
  290. long heapused() {
  291.   struct heapinfo hi;  long t=0;
  292.   if (heapcheck()<0) {
  293.     printf(msg[28]); pause;
  294.     return -1;
  295.   }
  296.   hi.ptr=NULL;
  297.   while (heapwalk(&hi)==2)
  298.     if (hi.in_use) t+=hi.size;
  299.   return t;
  300. }
  301.  
  302. /*-----------------------------------------------------------------
  303.    display menu
  304.    if the corner is 200, then no redraw is necessary.
  305. */
  306. void show_menu(void) {
  307.   int i,j,x=999,y=0; time_t t;
  308.   textattr(mcolor);
  309.   gettext(1,ti.screenheight,1,ti.screenheight,&i);
  310.   if ((i&255)!=200 || rand()<6000) {
  311.     for (i=0; i<numm; ++i) if (menu[i].name[0]!='.') {
  312.       if (x > ti.screenwidth-mwidth+1) { x=1; ++y; }
  313.       menu[i].x = x;
  314.       menu[i].y = y;
  315.       gotoxy(x,y);
  316.       if (x>1) putch(vline); else putch(' ');
  317.       cputs(menu[i].name);
  318.       for (j=strlen(menu[i].name)+1; j<mwidth; ++j) putch(' ');
  319.       x+=mwidth;
  320.     }
  321.     mheight = y+1;         /* number of lines used  by the menu */
  322.     relxy(-1,0);
  323.     for (x=wherex(); x>1 && x<=ti.screenwidth; ++x)
  324.       if (x%mwidth!=1) putch(' '); else putch(vline);
  325.  
  326.     /*  MAKE THE BOX AROUND THE FORMULA  */
  327.     if (ch8) {
  328.       gotoxy(1,y+1);
  329.       putch(201);
  330.       for (i=2; i<ti.screenwidth; ++i) putch(205);
  331.       putch(187);
  332.       gotoxy(1,ti.screenheight);
  333.       putch(200);
  334.       for (i=2; i<ti.screenwidth; ++i) putch(205);
  335.       putch(188);
  336.     }
  337.     gotoxy((ti.screenwidth-strlen(top))/2,mheight);
  338.     cputs(top);
  339.   }
  340.   if (ch8)
  341.     for (i=mheight+1; i<ti.screenheight; ++i) {
  342.       gotoxy(1,i); putch(186); gotoxy(ti.screenwidth,i); putch(186);
  343.     }
  344.   gotoxy(5,ti.screenheight);
  345.   t=time(0);
  346.   cprintf(" %.5s  %2lu%% ",ctime(&t)+11,100*heapused()/heapsz);
  347.   cputs(bottom);
  348.   gotoxy(2,ti.screenheight-1);
  349. }
  350. /*-----------------------------------------------------------------
  351.    Check for menu select
  352. */
  353. int selection(int x, int y) {
  354.   int i;
  355.   for (i=0; i<numm; ++i)
  356.     if (x>=menu[i].x && x<menu[i].x+mwidth && y==menu[i].y)
  357.       return menu[i].fid;
  358.   if (y==mheight) return PRV;
  359.   if (x==1) return PPL;
  360.   if (x==ti.screenwidth) return PPR;
  361.   if (y==ti.screenheight) return NXT;
  362.   return -1;
  363. }
  364. /*--------------------------------------------------------------------
  365.    display expressions (as many as possible) starting at p.
  366. */
  367. void display(node *p) {
  368.   int x,y,i,ts=0;
  369.  
  370.   if (tgt) {
  371.     resize(tgt,0);
  372.     ts = ti.screenheight/2;
  373.     if (ts > tgt->sy) ts=tgt->sy;
  374.   }
  375.   y=mheight+1;
  376.   numsee = 0;
  377.   while (p) {
  378.     resize(p,0);
  379.     x = (ti.screenwidth-2 - p->sx)/2 + 2 + panx;
  380.     if (p->msg && y+ts+1+p->sy < ti.screenheight) {
  381.       gotoxy(1,y);
  382.       textattr(bold2);  cprintf("%s",p->msg);  textattr(norm);
  383.       y = wherey()-1;
  384.     }
  385.     y += p->sy+1;
  386.     if (y+ts >= ti.screenheight) break;
  387.     show(p,0,x,y - (p->sy+1)/2);
  388.     p = p->next;
  389.     ++numsee;
  390.   }
  391.   if (!p && y+ts+1 < ti.screenheight) {          /* end of list */
  392.     gotoxy((ti.screenwidth-strlen(endlist))/2,y+1);
  393.     cputs(endlist);
  394.   }
  395.   if (ts) {
  396.     x = (ti.screenwidth-2 - tgt->sx)/2 + 2 + panx;
  397.     y = ti.screenheight - ts + tgt->sy/2;
  398.     show(tgt,0,x,y);
  399.     textattr(mcolor);
  400.     gotoxy(2,ti.screenheight-ts-1);
  401.     for (i=2; i<ti.screenwidth; ++i) putch(hline);
  402.     gotoxy(4,ti.screenheight-ts-1);
  403.     cputs(keyname);
  404.     textattr(norm);
  405.   }
  406. }
  407.  
  408. /*--------------------------------------------------------------------
  409.    debug print out -- return 0 if 'g' is pressed
  410. */
  411. int debug(node *p)  {
  412.   int x,y;
  413.   window(1,mheight+1,ti.screenwidth,ti.screenheight-1);
  414.   textattr(norm);
  415.   clrscr();
  416.   cprintf(msg[35]);
  417.   resize(p,0);
  418.   x = (ti.screenwidth-2 - p->sx)/2 + 2 + panx;
  419.   y = ti.screenheight/2;
  420.   show(p,0,x,y);
  421.   window(1,1,ti.screenwidth,ti.screenheight);
  422.   return 'g'!=getch();
  423. }
  424. /*-----------------------------------------------------------------
  425.    which node is pointed to?
  426. */
  427. node *find_node(node *p,int x,int y) {
  428.   int i; node *t;
  429.   switch (p->kind) {
  430.   case ADD:  case MUL:  case EQU:
  431.   case EXP:  case SUB:
  432.     if (x == p->px && y==p->py) {
  433.       return p;
  434.     }
  435.     break;
  436.   case DIV:
  437.     if (x >= p->px && y==p->py &&
  438.         x < (p->px+p->sx)) {
  439.       return p;
  440.     }
  441.     break;
  442.   case FUN:
  443.     if (x >= p->px && y==p->py &&
  444.         x < (p->px+strlen(p->name))) {
  445.       return p;
  446.     }
  447.     break;
  448.   default:
  449.     if (x >= p->px && y==p->py &&
  450.         x < (p->px + p->sx)) {
  451.       return p;
  452.     }
  453.   }
  454.   for (i=0; i<p->nump; ++i)
  455.     if (!!(t=find_node(p->parm[i],x,y))) return t;
  456.   return NULL;
  457. }
  458.  
  459. /*-----------------------------------------------------------------
  460.    prompt the user for oneline input
  461.    return value is non-reuseable!
  462. */
  463. char *keyin(char *pmt) {
  464.   static char buf[160]; int i;
  465.   window(1,ti.screenheight-4,ti.screenwidth-1,ti.screenheight-1);
  466.   textattr(norm);
  467.   clrscr();
  468.   cputs(pmt);
  469.   cputs("\r\n");
  470.   buf[0] = sizeof buf - 7;
  471.   cgets(buf); buf[0]=buf[1]=' ';
  472.   window(1,1,ti.screenwidth,ti.screenheight);
  473.   if (!buf[2]) strcpy(buf+2,"*.ae");
  474.   i = strlen(buf);
  475.   while (strchr(buf+2,'*') || strchr(buf+2,'?') || buf[i-1]=='\\') {
  476.     clrscr();
  477.     memmove(buf+7,buf+2,i-1);
  478.     memcpy(buf,"dir /w ",7);
  479.     printf("'%s'\n",buf);
  480.     system(buf);
  481.     printf("%s",pmt);
  482.     gets(buf+2);
  483.     i = strlen(buf);
  484.   }
  485.   if (i<4 || !strchr(buf+i-4,'.')) strcat(buf,".ae");
  486.   return buf+2;
  487. }
  488. /*-----------------------------------------------------------------
  489.    show help file
  490. */
  491. void showhelp(char *argv0) {
  492.   FILE *f;
  493.   int i,c=0;
  494.   static char s[85];
  495.  
  496. /*  strcpy(s,argv0);
  497.   strcpy(s+strlen(argv0)-4,lang);      don't use exe path */
  498.   i=*argv0;
  499.   strcpy(s,"alged");
  500.   strcat(s,lang);
  501.   strcat(s,".hlp");
  502.   f = fopen(s,"r");
  503.   if (!f) { printf(msg[16],s);
  504.     pause; return;
  505.   }
  506.   textattr(norm);
  507.   clrscr();
  508.   i = ti.screenheight-1;
  509.   while (!feof(f)) {
  510.     printf(fgets(s,80,f));
  511.     if (!--i) {
  512.       i = ti.screenheight-4;
  513.       while (!(c=getch()));
  514.       if (c==27) break;
  515.     }
  516.   }
  517.   if (c!=27) getch();
  518.   fclose(f);
  519. }
  520.  
  521. /*-----------------------------------------------------------------
  522.    load menu def
  523. */
  524. int loadmenu(char *argv0) {
  525.   FILE *f;
  526.   int i,c=0;
  527.   static char s[85];
  528.  
  529.   i=*argv0;
  530.   /*
  531.   strcpy(s,argv0);
  532.   strcpy(s+strlen(argv0)-4,lang);      don't use exe path */
  533.   strcpy(s,"alged");
  534.   strcat(s,lang);
  535.   strcat(s,".mnu");
  536.   f = fopen(s,"r");
  537.   if (!f) { printf(msg[16],s);
  538.     pause; return 1;
  539.   }
  540.   for (i=0; i<MAXM; ++i) msg[i]="[message not found]\n";
  541.   while (!feof(f)) {
  542.     fscanf(f,"%s",s);
  543.     if (!strcmp(s,"item")) {
  544.       c=0;
  545.       fscanf(f," \"%[^\"]\" %d %d",s,&i,&c);
  546.       if (!c) fscanf(f," '%c'",&c);
  547.       strcpy(menu[numm].name,s);
  548.       menu[numm].fid=i;
  549.       menu[numm++].hot=c;
  550.     }
  551.     else if (*s==';') {
  552.       fgets(s,sizeof s,f);
  553.     }
  554.     else if (!strcmp(s,"bottom")) {
  555.       fscanf(f," \"%[^\"]\"",bottom);
  556.     }
  557.     else if (!strcmp(s,"key")) {
  558.       fscanf(f," \"%[^\"]\"",keyname);
  559.     }
  560.     else if (!strcmp(s,"top")) {
  561.       fscanf(f," \"%[^\"]\"",top);
  562.     }
  563.     else if (!strcmp(s,"endlist")) {
  564.       fscanf(f," \"%[^\"]\"",endlist);
  565.     }
  566.     else if (!strcmp(s,"width")) {
  567.       fscanf(f,"%d",&mwidth);
  568.     }
  569.     else if (!strcmp(s,"msg")) {
  570.       fscanf(f,"%d ",&i);
  571.       fgets(s,sizeof s,f);
  572.       c = strlen(s);
  573.       if (s[c-2]=='$') s[c-2]=0;
  574.       if (i>=0&&i<MAXM) {
  575.         msg[i]=malloc(strlen(s)+1);
  576.         strcpy(msg[i++],s);
  577.       }
  578.     }
  579.   }
  580.   fclose(f);
  581.   return 0;
  582. }
  583.